home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_10_01 / cmenu.exe / RMENU1.C < prev    next >
Text File  |  1991-11-12  |  8KB  |  372 lines

  1. /************************************************************
  2.  *    Program: RMENU Menu Interpreter
  3.  *  Module: rmenu1.c
  4.  *        Main and Utility Functions
  5.  *    Written by: Leor Zolman, 7/91
  6.  ************************************************************/
  7.  
  8. #define    MASTER
  9. #include "cmenu.h"
  10. #include "rcmenu.h"
  11.  
  12. #if __STDC__
  13. #    include <stdarg.h>
  14. #else
  15. #    include <varargs.h>
  16. #endif
  17.  
  18. /************************************************************
  19.  * main():
  20.  *    Initialize the program and run
  21.  *    the master menu
  22.  ************************************************************/
  23.  
  24. main(argc, argv)
  25. int argc;
  26. char **argv;
  27. {
  28.     char *mname = "menu";
  29.     int i, j;
  30.  
  31.     debug = 0;                    /* No debugging by default        */
  32.  
  33.                                 /* Process command line options: */
  34.     for (i = 1; i < argc; i++)
  35.         if (argv[i][0] == '-')
  36.         {
  37.             switch (tolower(argv[i][1]))
  38.             {
  39.                 case 'd':    debug = TRUE;
  40.                             break;
  41.  
  42.                 default:    fprintf(stderr, "Unknown option: '%s'\n",
  43.                                         argv[i]);
  44.                             exit(0);
  45.             }
  46.             for (j = i; j < argc - 1; j++)    /* compress */
  47.                 argv[j] = argv[j + 1];        /* arg list */
  48.             argc--;
  49.             i--;
  50.         }
  51.  
  52.     init_win();        /* initialize curses */
  53.  
  54.     if (argc == 2)
  55.         mname = argv[1];
  56.  
  57.     nestlev = 0;
  58.     do_menu("", mname);
  59.     free_menus();
  60.     close_win();
  61.     return OK;
  62. }
  63.  
  64.  
  65. /************************************************************
  66.  * init_win():
  67.  *    Initialize Curses system.
  68.  ************************************************************/
  69.  
  70. Void init_win()
  71. {
  72.         /* initialize screen, and check for failure */
  73.     if (initscr() == INIT_FAIL)
  74.     {
  75.         printf("initscr failed!\n");
  76.         exit(1);
  77.     }
  78.  
  79.     tty_curses();    /* set tty modes for curses    */
  80.     return;
  81. }
  82.  
  83.  
  84. /************************************************************
  85.  * close_win(): 
  86.  *    Terminate Curses system
  87.  ************************************************************/
  88.  
  89. Void close_win()
  90. {
  91.     clear();
  92.     noraw();
  93.     refresh();                /* This is so cursor shows back up    */
  94.     endwin();
  95. }
  96.  
  97.  
  98. /************************************************************
  99.  * do_menu(): 
  100.  *    Run a compiled menu file, supporting recursive
  101.  *    calls for nested external menus.
  102.  *    Default command/menu path is supplied as "path".
  103.  ************************************************************/
  104.  
  105. int do_menu(path, file)
  106. char *path, *file;
  107. {
  108.     char pathname[MAX_PATH];
  109.     
  110.     strcpy(pathname, path);
  111.     if (*path) 
  112.         strcat(pathname, "/");
  113.     strcat(pathname, file);
  114.     strcat(pathname, ".mnc");
  115.  
  116.     if (ld_menu(pathname) == ERROR)
  117.         return EXITALL;
  118.  
  119.     return sub_menu(0, path);    /* run main menu in file */ 
  120. }
  121.  
  122.         
  123. /************************************************************
  124.  * ld_menu():
  125.  *    Load a compiled menu object file from disk,
  126.  *    into nesting level nestlev, allocating memory
  127.  *    as required.
  128.  *    For each menu in the menu file being loaded,
  129.  *    compute screen placement as per spacing/columns
  130.  *    specifications and the total number of items.
  131.  ************************************************************/
  132.  
  133. int ld_menu(path)
  134. char *path;
  135. {
  136.     LEVELS *Levp = &LMenus[nestlev];
  137.     MENU *Mp;
  138.     ITEM *Ip;
  139.     MENU2 *M2p;
  140.  
  141.     FILE *fp;
  142.     int i, j, k, l;
  143.     
  144.     if ((fp = fopen(path, "rb")) == NULL)
  145.         return fatal("Can't open %s\n", path);
  146.     
  147.     if (fread((Void *) &Levp->n_menus, sizeof (int), 1, fp)
  148.                     != 1)
  149.         return fatal("Error reading menu count from %s\n", path);
  150.     
  151.     for (i = 0; i < Levp->n_menus; i++)
  152.     {
  153.         if (i < Levp -> max_menus)
  154.             M2p = Levp -> Menus[i];
  155.         else                        /* allocate memory for Menu    */
  156.         {
  157.             M2p = Levp -> Menus[i] = (MENU2 *) malloc(sizeof(MENU2));
  158.             if (M2p == NULL)
  159.                 return fatal("Out of memory loading %s\n", path);
  160.             Levp -> max_menus++;
  161.             M2p -> most_items = 0;
  162.         }
  163.  
  164.         Mp = &M2p -> Menu;
  165.         
  166.         if (fread((Void *) Mp, sizeof(MENU), 1, fp) != 1)
  167.             return fatal("Error reading Menu data from %s\n", path);
  168.         
  169.     /* Now determine screen placement strategy. */
  170.  
  171.         placement(Mp);
  172.  
  173.         M2p -> field_len = min(MAX_TXTWID, 
  174.                     (SCREEN_COLS / Mp -> columns) - 5);
  175.  
  176.     /* Read in each item, and assign screen coordinate info */
  177.     /* to each on-the-fly as per spacing/column parameters    */
  178.         
  179.         for (j = 0; j < Mp -> nitems; j++)
  180.         {
  181.             if (j < M2p -> most_items)
  182.                 Ip = M2p -> Items[j];
  183.             else
  184.             {
  185.                 Ip = M2p -> Items[j] = (ITEM *) malloc(sizeof(ITEM));
  186.                 if (Ip == NULL)
  187.                     fatal("Out of memory loading %s, menu #%d/item #%d",
  188.                         path, i,j);
  189.                 M2p -> most_items++;
  190.             }
  191.             if (fread((Void *) Ip, sizeof(ITEM), 1, fp) != 1)
  192.                 return fatal("Error reading %s\n", path);
  193.  
  194.             Ip -> text[M2p -> field_len - 1] = '\0'; /* truncate */
  195.  
  196.             if ((Ip -> acttyp == ACT_LMENU ||
  197.                  Ip -> acttyp == ACT_EMENU) &&
  198.                 strlen(Ip -> text) + 6 < M2p -> field_len)
  199.             {
  200.                 int limit;
  201.                 
  202.                 limit = min (Mp -> widest + 2,
  203.                         M2p -> field_len - 7);
  204.                 for (k = strlen(Ip -> text);
  205.                         k < limit && k < (MAX_TXTWID - 6); k++)
  206.                     strcat(Ip -> text, " ");
  207.                 strcat(Ip -> text, "(MENU)");
  208.             }
  209.  
  210.             M2p -> coords[j].ypos = 
  211.                     HOME_Y + (j % (MAX_IROWS / Mp -> spacing))
  212.                                 * Mp -> spacing;
  213.  
  214.             M2p -> coords[j].xpos = 
  215.                     HOME_X + (j / (MAX_IROWS / Mp -> spacing))
  216.                             * (SCREEN_COLS / Mp -> columns);
  217.  
  218.             M2p -> coords[j].spaces_needed = 
  219.                     min(M2p -> field_len, Mp -> widest)
  220.                             - strlen(Ip -> text);
  221.         }
  222.     }
  223.     fclose(fp);
  224.     return OK;
  225. }
  226.  
  227.  
  228. /************************************************************
  229.  * placement():
  230.  *    Calculate values for columns and spacing 
  231.  *    for the given Menu:
  232.  ************************************************************/
  233.  
  234. Void placement(Mp)
  235. MENU *Mp;
  236. {
  237.     int columns = Mp -> columns;
  238.     int spacing = Mp -> spacing;
  239.     int nitems = Mp -> nitems;
  240.  
  241.     /* Step 1: fill in real values if either    */
  242.     /*    columns or spacing was not specified:    */
  243.  
  244.     if (spacing == DEFAULT && columns == DEFAULT)
  245.     {
  246.         if (nitems <= (MAX_IROWS / 2))
  247.         {
  248.             Mp -> columns = 1;
  249.             Mp -> spacing = 2;
  250.         }
  251.         else if (nitems <= MAX_IROWS)
  252.             if ((Mp -> widest * 2 + 5) <= SCREEN_COLS)
  253.                 Mp -> columns = Mp -> spacing = 2;
  254.             else
  255.                 Mp -> columns = Mp -> spacing = 1;
  256.         else
  257.         {
  258.             Mp -> spacing = 1;
  259.             Mp -> columns = (nitems - 1) / MAX_IROWS + 1;
  260.         }
  261.     }
  262.     else if (spacing == DEFAULT)
  263.         Mp -> spacing =
  264.                 (nitems <= (MAX_IROWS / 2)) ? 2 : 1;
  265.     else if (columns == DEFAULT)
  266.         if (Mp -> spacing == 1)
  267.             Mp -> columns = (nitems - 1) / MAX_IROWS + 1;
  268.         else
  269.             Mp -> columns = (nitems - 1) / (MAX_IROWS / 2) + 1;
  270.         
  271.     /* Step 2: Adjust if out of range: */
  272.             
  273.     while (MAX_IROWS / Mp -> spacing * Mp -> columns < nitems)
  274.         if (Mp -> spacing != 1)
  275.             Mp -> spacing = 1;
  276.         else
  277.             Mp -> columns++;
  278.     return;
  279. }
  280.  
  281.  
  282. /************************************************************
  283.  * free_menus():
  284.  *    Free up memory allocated for ALL menu items:
  285.  ************************************************************/
  286.  
  287. Void free_menus()
  288. {
  289.     int i, j, k;
  290.     MENU2 *m2p;
  291.     
  292.     for (i = 0; i < MAX_NEST; i++)
  293.         for (j = 0; j < LMenus[i].max_menus; j++)
  294.         {
  295.             m2p = LMenus[i].Menus[j];
  296.             for (k = 0; k < m2p -> most_items; k++)
  297.                 free(m2p -> Items[k]);
  298.             free(m2p);
  299.         }
  300. }
  301.  
  302.  
  303. /************************************************************
  304.  * fatal(): Complain and exit.
  305.  ************************************************************/
  306.  
  307. #if __STDC__                 /* use ANSI variable-#-of-args method    */
  308.  
  309. int fatal (char *fmt, ...)
  310. {
  311.     va_list arglist;
  312.     
  313.     va_start(arglist, fmt);
  314.  
  315. #else                        /* or old varargs method:                */
  316.  
  317. int fatal(fmt, va_alist)
  318. char *fmt;
  319. va_dcl
  320. {
  321.     va_list arglist;
  322.     
  323.     va_start(arglist);
  324.  
  325. #endif
  326.                             /* rest of function same, ANSI or not:    */
  327.     pre_shell();
  328.     beep();
  329.     fprintf(stderr, "\n\nFatal error in rmenu: ");
  330.     vfprintf(stderr, fmt, arglist);
  331.     va_end(arglist);
  332.     fprintf(stderr, "(Press any key to continue)");
  333.     post_shell();
  334.     (Void)getch();
  335.     return ERROR;
  336. }
  337.  
  338.  
  339. /************************************************************
  340.  * put_msg(): Display a message on the menu screen
  341.  *    Return the character typed to continue
  342.  ************************************************************/
  343.  
  344. #if __STDC__
  345.   int put_msg (int bell, char *text, ...)
  346. #else
  347.   int put_msg(bell, text)
  348.   int b